<!DOCTYPE html>
<html lang="zh-CN">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>网络实验AI助手</title>
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css">
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.1/font/bootstrap-icons.css">
    <style>
        /* 莫兰迪色系 */
        :root {
            --morandiBlue: #2F3B45; /* primary: 石板灰 */
            --morandiGreen: #ECECEC; /* 中性浅灰，用于记忆项 */
            --morandiPink: #EAEAEA; /* 中性浅灰2，用于纠正项 */
            --morandiBeige: #E7E7E4; /* 表面副色 */
            --morandiGray: #E5E7EB; /* 边框/分割线 */
            --morandiDarkGray: #6B7280; /* 次级文字 */
            --morandiLightBlue: #D6D6D3; /* 主色浅替代 */
            --morandiBg: #F5F5F2; /* 全局背景 */
            --morandiText: #2F2F2F; /* 主文字 */
            --morandiShadow: rgba(0, 0, 0, 0.08); /* 阴影 */
        }

        body {
            font-family: 'Microsoft YaHei', sans-serif;
            background-color: var(--morandiBg);
            padding-bottom: 50px;
            color: var(--morandiText);
        }

        /* 侧边栏样式 */
        #sidebar {
            position: relative;
            width: 0;
            min-width: 0;
            transition: width 0.3s ease, min-width 0.3s ease;
            background-color: var(--morandiBg);
            overflow: hidden;
            height: 100%;
            display: flex;
            flex-direction: column;
        }

        #sidebar.show {
            width: 200px;
            min-width: 200px;
            box-shadow: 2px 0 10px rgba(0, 0, 0, 0.1);
        }

        .btn-icon {
            width: 32px;
            height: 32px;
            padding: 0;
            display: inline-flex;
            align-items: center;
            justify-content: center;
            border-radius: 4px;
        }

        #sidebarConversationsList {
            flex: 1;
            overflow-y: auto;
        }

        #chat-content-wrapper {
            transition: width 0.3s ease;
            height: 100%;
        }

        .chat-row {
            display: flex;
            height: calc(100vh - 60px);
            min-height: 700px;
            overflow: hidden;
        }

        .header {
            background-color: var(--morandiBlue);
            color: white;
            padding: 15px 0;
            margin-bottom: 20px;
            box-shadow: 0 2px 10px var(--morandiShadow);
        }

        .main-container {
            max-width: 1200px;
            margin: 0 auto;
        }

        .card {
            border-radius: 12px;
            box-shadow: 0 4px 8px var(--morandiShadow);
            margin-bottom: 20px;
            border: none;
            overflow: hidden;
        }

        .card-header {
            background-color: var(--morandiLightBlue);
            color: var(--morandiText);
            border-bottom: 1px solid var(--morandiGray);
            padding: 12px 16px;
            font-weight: 500;
        }

        .card-body {
            padding: 16px;
        }

        .chat-container {
            padding: 15px;
            background-color: white;
            border-radius: 0;
            overflow-y: auto !important;
            max-height: 100%;
        }

        .message {
            padding: 12px 16px;
            border-radius: 12px;
            margin-bottom: 12px;
            max-width: 85%;
            box-shadow: 0 2px 5px var(--morandiShadow);
        }

        .user-message {
            background-color: var(--morandiBlue);
            color: white;
            margin-left: auto;
        }

        .ai-message {
            background-color: var(--morandiBeige);
            color: var(--morandiText);
            white-space: pre-wrap;
            /* 保留换行符 */
        }

        /* 调整列表项间距 */
        .ai-message p {
            margin-bottom: 0.5rem;
        }

        /* 使列表项更紧凑 */
        .ai-message {
            line-height: 1.4;
        }

        .memory-item {
            padding: 10px;
            margin-bottom: 8px;
            border-radius: 8px;
            background-color: var(--morandiGreen);
            color: var(--morandiText);
        }

        .correction-item {
            background-color: var(--morandiPink);
        }

        #imagePreview {
            display: flex;
            flex-wrap: wrap;
            gap: 10px;
            margin-top: 10px;
        }

        .image-preview-container {
            position: relative;
            display: inline-block;
            margin: 5px;
        }

        .preview-image {
            width: 80px;
            height: 80px;
            object-fit: cover;
            border-radius: 8px;
            border: 1px solid var(--morandiGray);
            transition: all 0.2s ease;
            cursor: pointer;
        }

        .image-preview-container:hover .preview-image {
            opacity: 0.7;
        }

        /* 图片预览模态框样式 */
        .image-modal {
            display: none;
            position: fixed;
            z-index: 1050;
            left: 0;
            top: 0;
            width: 100%;
            height: 100%;
            overflow: auto;
            background-color: rgba(0, 0, 0, 0.8);
        }

        .image-modal-content {
            margin: auto;
            display: block;
            max-width: 90%;
            max-height: 90%;
            margin-top: 2%;
        }

        .image-modal-close {
            position: absolute;
            top: 15px;
            right: 25px;
            color: #f1f1f1;
            font-size: 40px;
            font-weight: bold;
            transition: 0.3s;
            cursor: pointer;
        }

        .image-modal-close:hover {
            color: #bbb;
        }

        .delete-image {
            position: absolute;
            top: -8px;
            right: -8px;
            background-color: var(--morandiPink);
            color: white;
            border-radius: 50%;
            width: 22px;
            height: 22px;
            text-align: center;
            line-height: 20px;
            font-size: 14px;
            cursor: pointer;
            opacity: 0;
            transition: opacity 0.2s ease;
            box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);
        }

        .image-preview-container:hover .delete-image {
            opacity: 1;
        }

        .upload-status {
            margin-top: 5px;
            font-size: 12px;
            color: var(--morandiDarkGray);
        }

        .message-row {
            display: flex;
            align-items: flex-start;
            gap: 10px;
            width: 100%;
        }
        .message-row.ai {
            flex-direction: row;
            justify-content: flex-start;
        }
        .message-row.user {
            flex-direction: row-reverse;
            justify-content: flex-start;
        }
        .message-avatar {
            width: 40px;
            height: 40px;
            border-radius: 50%;
            box-shadow: 0 2px 4px var(--morandiShadow);
            overflow: hidden;
            flex-shrink: 0;
            background-color: transparent;
        }
        .message-avatar img {
            width: 100%;
            height: 100%;
            display: block;
        }
        .message-row .user-message {
            margin-left: 0;
        }

        .chat-attachments {
            display: flex;
            flex-wrap: wrap;
            gap: 8px;
            margin-top: 8px;
        }
        .chat-attachments .chat-attachment {
            width: 80px;
            height: 80px;
            object-fit: cover;
            border-radius: 8px;
            border: 1px solid var(--morandiGray);
            box-shadow: 0 1px 3px var(--morandiShadow);
            cursor: pointer;
        }

        .loading {
            display: inline-block;
            width: 20px;
            height: 20px;
            border: 3px solid rgba(139, 168, 183, 0.3);
            border-radius: 50%;
            border-top-color: var(--morandiBlue);
            animation: spin 1s ease-in-out infinite;
        }

        @keyframes spin {
            to {
                transform: rotate(360deg);
            }
        }

        /* 按钮样式 */
        .btn-primary {
            background-color: var(--morandiBlue);
            border-color: var(--morandiBlue);
        }

        .btn-primary:hover {
            background-color: #7a97a6;
            border-color: #7a97a6;
        }

        .btn-secondary {
            background-color: var(--morandiGray);
            border-color: var(--morandiGray);
            color: var(--morandiText);
        }

        .btn-secondary:hover {
            background-color: #c5c5c5;
            border-color: #c5c5c5;
            color: var(--morandiText);
        }

        .btn-danger {
            background-color: #e8a9a9;
            border-color: #e8a9a9;
        }

        .btn-danger:hover {
            background-color: #d89595;
            border-color: #d89595;
        }

        /* 表单控件 */
        .form-control:focus {
            border-color: var(--morandiBlue);
            box-shadow: 0 0 0 0.25rem rgba(139, 168, 183, 0.25);
        }

        /* 输入框美化：圆角、内边距、自适应高度、最大高度并滚动 */
        #questionInput {
            min-height: 42px;
            max-height: 160px;
            /* 超过显示内部滚动 */
            padding: 10px 12px;
            border-radius: 10px;
            border: 1px solid #dfe7e9;
            box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.02);
            font-size: 14px;
            line-height: 1.4;
            background: #ffffff;
            transition: box-shadow 0.15s ease, border-color 0.15s ease;
            resize: none;
            /* 禁止拖拽改变大小 */
            overflow: auto;
        }

        #questionInput:focus {
            border-color: var(--morandiBlue);
            box-shadow: 0 4px 12px rgba(139, 168, 183, 0.12);
            outline: none;
        }

        /* 调整输入组，使按钮垂直居中 */
        .input-group {
            display: flex;
            gap: 8px;
            align-items: center;
        }

        .input-group .btn {
            height: 42px;
            border-radius: 10px;
            padding: 0 14px;
            display: inline-flex;
            align-items: center;
            justify-content: center;
        }

        /* 更好看的用户消息气泡 */
        .user-message {
            background-color: var(--morandiBlue);
            color: #fff;
            margin-left: 0;
            text-align: right;
        }

        /* 美化AI消息中的代码块和列表（Markdown 渲染） */
        /* 更深的代码块背景，增强对比度，并增加复制按钮的占位 */
        .ai-message pre {
            background: #0f1720;
            /* 更深背景 */
            color: #e6eef7;
            /* 代码颜色 */
            padding: 12px 12px 16px 12px;
            border-radius: 8px;
            overflow: auto;
            position: relative;
            /* 以便放置绝对定位的复制按钮 */
            box-shadow: 0 2px 6px rgba(0, 0, 0, 0.12);
        }

        .ai-message code {
            background: transparent;
            color: #e6eef7;
            padding: 2px 6px;
            border-radius: 4px;
            font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, 'Roboto Mono', 'Courier New', monospace;
        }

        /* 代码复制按钮 */
        .code-copy-btn {
            position: absolute;
            top: 8px;
            right: 8px;
            background: rgba(255, 255, 255, 0.06);
            color: #e6eef7;
            border: 1px solid rgba(255, 255, 255, 0.06);
            padding: 4px 8px;
            border-radius: 6px;
            font-size: 12px;
            cursor: pointer;
            backdrop-filter: blur(4px);
            transition: background 0.12s ease;
            z-index: 5;
        }

        .code-copy-btn:hover {
            background: rgba(255, 255, 255, 0.12);
        }

        .code-copy-btn.copied {
            background: rgba(34, 197, 94, 0.9);
            border-color: rgba(34, 197, 94, 0.9);
            color: white;
        }

        /* 滚动条样式 */
        ::-webkit-scrollbar {
            width: 8px;
        }

        ::-webkit-scrollbar-track {
            background: var(--morandiBeige);
            border-radius: 10px;
        }

        ::-webkit-scrollbar-thumb {
            background: var(--morandiBlue);
            border-radius: 10px;
        }

        ::-webkit-scrollbar-thumb:hover {
            background: #7a97a6;
        }

        /* 打字效果相关样式 */
        .typing {
            position: relative;
        }

        .typing::after {
            content: '|';
            position: absolute;
            right: -2px;
            animation: cursor 1s infinite;
        }

        @keyframes cursor {

            0%,
            100% {
                opacity: 1;
            }

            50% {
                opacity: 0;
            }
        }
    </style>
</head>

<body>
    <div class="header">
        <div class="container">
            <h1>计算机网络实验AI助手</h1>
            <p>基于通义千问API的网络实验PDF处理和问答系统</p>
        </div>
    </div>

    <div class="container-fluid main-container">
        <!-- 主界面使用标签页布局 -->
        <ul class="nav nav-tabs mb-3" id="mainTab" role="tablist">
            <li class="nav-item" role="presentation">
                <button class="nav-link active" id="chat-tab" data-bs-toggle="tab" data-bs-target="#chat-pane"
                    type="button" role="tab" aria-controls="chat-pane" aria-selected="true">对话</button>
            </li>
            <li class="nav-item" role="presentation">
                <button class="nav-link" id="pdf-tab" data-bs-toggle="tab" data-bs-target="#pdf-pane" type="button"
                    role="tab" aria-controls="pdf-pane" aria-selected="false">PDF管理</button>
            </li>
            <li class="nav-item" role="presentation">
                <button class="nav-link" id="search-tab" data-bs-toggle="tab" data-bs-target="#search-pane"
                    type="button" role="tab" aria-controls="search-pane" aria-selected="false">检索</button>
            </li>
            <li class="nav-item" role="presentation">
                <button class="nav-link" id="memory-tab" data-bs-toggle="tab" data-bs-target="#memory-pane"
                    type="button" role="tab" aria-controls="memory-pane" aria-selected="false">记忆管理</button>
            </li>
        </ul>

        <div class="tab-content" id="mainTabContent">
            <!-- 聊天对话面板 -->
            <div class="tab-pane fade show active" id="chat-pane" role="tabpanel" aria-labelledby="chat-tab">
                <div class="chat-row">
                    <!-- 侧边栏 -->
                    <div id="sidebar" class="p-0">
                        <div class="card border-0 h-100 d-flex flex-column bg-white">
                            <div class="card-header d-flex justify-content-between align-items-center py-2">
                                <h5 class="mb-0">历史对话</h5>
                                <div>
                                    <button id="newConversationSidebarBtn" class="btn btn-sm btn-icon btn-primary me-1"
                                        title="新建对话">
                                        <i class="bi bi-plus-lg"></i>
                                    </button>
                                    <button id="closeSidebarBtn" class="btn btn-sm btn-icon btn-outline-secondary"
                                        title="关闭">
                                        <i class="bi bi-x-lg"></i>
                                    </button>
                                </div>
                            </div>
                            <div id="sidebarConversationsList" class="list-group list-group-flush flex-grow-1 bg-white">
                                <div class="text-center my-3">
                                    <div class="spinner-border spinner-border-sm text-primary" role="status"></div>
                                    <p class="mt-2 small">加载对话...</p>
                                </div>
                            </div>
                            <div class="card-footer bg-white p-0" style="min-height: 20px;"></div>
                        </div>
                    </div>

                    <!-- 聊天主内容区 -->
                    <div id="chat-content-wrapper" class="flex-grow-1">
                        <div class="card h-100 d-flex flex-column">
                            <div class="card-header d-flex justify-content-between align-items-center">
                                <div class="d-flex align-items-center">
                                    <button id="toggleSidebarBtn" class="btn btn-sm btn-outline-secondary me-2"
                                        title="历史对话">
                                        <i class="bi bi-layout-sidebar"></i>
                                    </button>
                                    <h5 class="mb-0">与AI助手对话</h5>
                                </div>
                                <div>
                                    <button id="newConversationBtn" class="btn btn-sm btn-outline-primary me-2">
                                        新建对话
                                    </button>
                                    <button id="showHistoryImages" class="btn btn-sm btn-outline-secondary">
                                        历史图片
                                    </button>
                                </div>
                            </div>
                            <div class="card-body p-0 flex-grow-1 overflow-auto">
                                <div class="chat-container" id="chatContainer"
                                    style="height: 100%; overflow-y: auto !important;">
                                    <!-- 欢迎消息将通过JavaScript动态添加 -->
                                </div>
                            </div>
                            <div class="card-footer bg-white border-top">
                                <form id="queryForm" class="mb-2">
                                    <div class="input-group">
                                        <!-- 使用 textarea 支持多行与自适应高度 -->
                                        <textarea id="questionInput" class="form-control" placeholder="请输入您的问题..."
                                            rows="1" style="resize: none; overflow: hidden;" required></textarea>
                                        <button type="submit" class="btn btn-primary">发送</button>
                                    </div>
                                </form>
                                <div class="d-flex justify-content-between align-items-center">
                                    <div class="form-check">
                                        <input class="form-check-input" type="checkbox" id="searchDocsCheck" checked>
                                        <label class="form-check-label" for="searchDocsCheck">
                                            搜索文档
                                        </label>
                                    </div>
                                    <div>
                                        <label for="imageUpload" class="btn btn-sm btn-outline-secondary">
                                            添加图片
                                        </label>
                                        <input type="file" id="imageUpload" accept="image/*" multiple
                                            style="display: none;">
                                    </div>
                                </div>
                                <div id="imagePreview" class="mt-2"></div>
                                <div id="uploadStatus" class="upload-status"></div>
                            </div>
                        </div>
                    </div>
                </div>
            </div>

            <!-- PDF管理面板 -->
            <div class="tab-pane fade" id="pdf-pane" role="tabpanel" aria-labelledby="pdf-tab">
                <div class="row">
                    <div class="col-md-6">
                        <!-- PDF上传 -->
                        <div class="card mb-4">
                            <div class="card-header">
                                <h5 class="mb-0">上传PDF文件</h5>
                            </div>
                            <div class="card-body">
                                <form id="uploadForm">
                                    <div class="mb-3">
                                        <label for="pdfFile" class="form-label">选择PDF文件</label>
                                        <input class="form-control" type="file" id="pdfFile" accept=".pdf" multiple>
                                    </div>
                                    <div class="mb-3">
                                        <div class="form-check">
                                            <input class="form-check-input" type="radio" name="fileType" id="guideType"
                                                value="guide" checked>
                                            <label class="form-check-label" for="guideType">
                                                实验指导书
                                            </label>
                                        </div>
                                        <div class="form-check">
                                            <input class="form-check-input" type="radio" name="fileType" id="reportType"
                                                value="report">
                                            <label class="form-check-label" for="reportType">
                                                实验报告
                                            </label>
                                        </div>
                                    </div>
                                    <div class="mb-3">
                                        <div class="form-check">
                                            <input class="form-check-input" type="checkbox" id="includeImagesCheck"
                                                checked>
                                            <label class="form-check-label" for="includeImagesCheck">
                                                <strong>启用AI图片识别</strong>（推荐）
                                            </label>
                                        </div>
                                        <small class="text-muted">AI会自动识别PDF中的图片内容（拓扑图、配置截图等），让搜索和问答更准确。<br>
                                            ⚠️ 注意：图片识别会增加处理时间和API调用量</small>
                                    </div>
                                    <button type="submit" class="btn btn-primary" id="uploadBtn">上传</button>
                                </form>
                                <div id="uploadStatus" class="mt-3"></div>
                            </div>
                        </div>
                    </div>

                    <div class="col-md-6">
                        <!-- 已上传PDF列表 -->
                        <div class="card mb-4">
                            <div class="card-header d-flex justify-content-between align-items-center">
                                <h5 class="mb-0">已上传PDF文件</h5>
                                <button id="refreshPdfList" class="btn btn-sm btn-outline-secondary">刷新列表</button>
                            </div>
                            <div class="card-body">
                                <div class="mb-3">
                                    <h6>实验指导书</h6>
                                    <ul id="guidesList" class="list-group">
                                        <li class="list-group-item text-muted">暂无文件</li>
                                    </ul>
                                </div>
                                <div class="mb-3">
                                    <h6>实验报告</h6>
                                    <ul id="reportsList" class="list-group">
                                        <li class="list-group-item text-muted">暂无文件</li>
                                    </ul>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
            </div>

            <!-- 检索面板 -->
            <div class="tab-pane fade" id="search-pane" role="tabpanel" aria-labelledby="search-tab">
                <div class="row">
                    <div class="col-md-4">
                        <!-- 直接检索 -->
                        <div class="card">
                            <div class="card-header">
                                <h5 class="mb-0">直接检索</h5>
                            </div>
                            <div class="card-body">
                                <form id="searchForm">
                                    <div class="mb-3">
                                        <label for="searchQuery" class="form-label">搜索关键词</label>
                                        <input type="text" class="form-control" id="searchQuery" placeholder="输入关键词..."
                                            required>
                                    </div>
                                    <div class="mb-3">
                                        <label class="form-label">搜索范围</label>
                                        <div class="form-check">
                                            <input class="form-check-input" type="radio" name="searchScope"
                                                id="scopeBoth" value="both" checked>
                                            <label class="form-check-label" for="scopeBoth">
                                                全部文档
                                            </label>
                                        </div>
                                        <div class="form-check">
                                            <input class="form-check-input" type="radio" name="searchScope"
                                                id="scopeGuides" value="guides">
                                            <label class="form-check-label" for="scopeGuides">
                                                仅实验指导书
                                            </label>
                                        </div>
                                        <div class="form-check">
                                            <input class="form-check-input" type="radio" name="searchScope"
                                                id="scopeReports" value="reports">
                                            <label class="form-check-label" for="scopeReports">
                                                仅实验报告
                                            </label>
                                        </div>
                                    </div>
                                    <div class="mb-3">
                                        <label for="resultLimit" class="form-label">结果数量</label>
                                        <input type="number" class="form-control" id="resultLimit" min="1" max="20"
                                            value="5">
                                    </div>
                                    <div class="mb-3">
                                        <label class="form-label">搜索类型</label>
                                        <div class="form-check">
                                            <input class="form-check-input" type="radio" name="searchType"
                                                id="semanticSearch" value="semantic" checked>
                                            <label class="form-check-label" for="semanticSearch">
                                                语义搜索（理解意思）
                                            </label>
                                        </div>
                                        <div class="form-check">
                                            <input class="form-check-input" type="radio" name="searchType"
                                                id="exactSearch" value="exact">
                                            <label class="form-check-label" for="exactSearch">
                                                精确匹配（关键词）
                                            </label>
                                        </div>
                                    </div>
                                    <button type="submit" class="btn btn-primary">搜索</button>
                                </form>
                            </div>
                        </div>
                    </div>
                    <div class="col-md-8">
                        <div class="card">
                            <div class="card-header">
                                <h5 class="mb-0">搜索结果</h5>
                            </div>
                            <div class="card-body">
                                <div id="searchResults">
                                    <div class="text-muted">请在左侧输入关键词进行搜索</div>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
            </div>

            <!-- 记忆管理面板 -->
            <div class="tab-pane fade" id="memory-pane" role="tabpanel" aria-labelledby="memory-tab">
                <div class="row">
                    <div class="col-md-6">
                        <!-- 添加记忆 -->
                        <div class="card mb-4">
                            <div class="card-header">
                                <h5 class="mb-0">添加新知识</h5>
                            </div>
                            <div class="card-body">
                                <form id="memoryForm">
                                    <div class="mb-3">
                                        <textarea class="form-control" id="factInput" rows="3"
                                            placeholder="输入要记住的事实或知识..."></textarea>
                                    </div>
                                    <div class="mb-3">
                                        <div class="form-check">
                                            <input class="form-check-input" type="checkbox" id="isCorrectionCheck">
                                            <label class="form-check-label" for="isCorrectionCheck">
                                                这是对之前知识的纠正
                                            </label>
                                        </div>
                                    </div>
                                    <button type="submit" class="btn btn-primary">添加到记忆</button>
                                </form>
                            </div>
                        </div>

                        <!-- 删除记忆 -->
                        <div class="card">
                            <div class="card-header">
                                <h5 class="mb-0">删除记忆</h5>
                            </div>
                            <div class="card-body">
                                <form id="deleteMemoryForm">
                                    <div class="mb-3">
                                        <label for="memoryIndex" class="form-label">记忆索引</label>
                                        <input type="number" class="form-control" id="memoryIndex" min="0" value="0"
                                            required>
                                    </div>
                                    <div class="mb-3">
                                        <div class="form-check">
                                            <input class="form-check-input" type="checkbox"
                                                id="deleteIsCorrectionCheck">
                                            <label class="form-check-label" for="deleteIsCorrectionCheck">
                                                删除纠正记忆（而非事实记忆）
                                            </label>
                                        </div>
                                    </div>
                                    <button type="submit" class="btn btn-danger">删除</button>
                                </form>
                            </div>
                        </div>
                    </div>

                    <div class="col-md-6">
                        <!-- 当前记忆 -->
                        <div class="card">
                            <div class="card-header">
                                <h5 class="mb-0">当前记忆</h5>
                            </div>
                            <div class="card-body">
                                <div id="memoryContainer" style="max-height: 400px; overflow-y: auto;">
                                    <div class="text-muted">暂无记忆数据</div>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>

    <!-- PDF内容模态框 -->
    <div class="modal fade" id="pdfContentModal" tabindex="-1" aria-labelledby="pdfContentModalLabel"
        aria-hidden="true">
        <div class="modal-dialog modal-xl modal-dialog-scrollable">
            <div class="modal-content">
                <div class="modal-header">
                    <h5 class="modal-title" id="pdfContentModalLabel">PDF内容</h5>
                    <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
                </div>
                <div class="modal-body">
                    <div id="pdfContent"></div>
                </div>
                <div class="modal-footer">
                    <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">关闭</button>
                </div>
            </div>
        </div>
    </div>

    <!-- 图片预览模态框 -->
    <div id="imageModal" class="image-modal">
        <span class="image-modal-close">&times;</span>
        <img class="image-modal-content" id="modalImage">
    </div>

    <!-- 历史图片模态框 -->
    <div class="modal fade" id="historyImagesModal" tabindex="-1" aria-labelledby="historyImagesModalLabel"
        aria-hidden="true">
        <div class="modal-dialog modal-lg">
            <div class="modal-content">
                <div class="modal-header">
                    <h5 class="modal-title" id="historyImagesModalLabel">历史上传图片</h5>
                    <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
                </div>
                <div class="modal-body">
                    <div id="historyImagesContainer" class="d-flex flex-wrap gap-3">
                        <div class="text-center w-100 my-5">
                            <div class="spinner-border text-primary" role="status"></div>
                            <p class="mt-2">正在加载图片...</p>
                        </div>
                    </div>
                </div>
                <div class="modal-footer">
                    <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">关闭</button>
                </div>
            </div>
        </div>
    </div>


    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
    <!-- Markdown parser -->
    <script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
    <script>
        document.addEventListener('DOMContentLoaded', function () {
            // 全局变量
            const chatContainer = document.getElementById('chatContainer');
            const queryForm = document.getElementById('queryForm');
            const questionInput = document.getElementById('questionInput');
            // 自动调整输入框高度（自适应内容）
            function autoResizeTextarea(el) {
                if (!el) return;
                el.style.height = 'auto';
                // 加 2px 以避免出现水平滚动条
                el.style.height = (el.scrollHeight + 2) + 'px';
            }
            if (questionInput) {
                // 初始化高度
                autoResizeTextarea(questionInput);
                // 在输入时调整高度
                questionInput.addEventListener('input', function () { autoResizeTextarea(this); });
                // 回车发送（Enter 发送，Shift+Enter 换行）
                questionInput.addEventListener('keydown', function (e) {
                    if (e.key === 'Enter' && !e.shiftKey) {
                        e.preventDefault();
                        // 支持 form.requestSubmit 在现代浏览器
                        if (typeof queryForm.requestSubmit === 'function') {
                            queryForm.requestSubmit();
                        } else {
                            // 兼容性回退
                            queryForm.dispatchEvent(new Event('submit', { bubbles: true, cancelable: true }));
                        }
                    }
                });
            }
            const searchDocsCheck = document.getElementById('searchDocsCheck');
            const uploadForm = document.getElementById('uploadForm');
            const uploadStatus = document.getElementById('uploadStatus');
            const memoryForm = document.getElementById('memoryForm');
            const memoryContainer = document.getElementById('memoryContainer');
            const imageUpload = document.getElementById('imageUpload');
            const imagePreview = document.getElementById('imagePreview');
            const showHistoryImages = document.getElementById('showHistoryImages');
            const historyImagesContainer = document.getElementById('historyImagesContainer');
            const newConversationBtn = document.getElementById('newConversationBtn');

            // 当前对话ID
            let currentConversationId = localStorage.getItem('currentConversationId') || null;
            let selectedImages = [];

            // 加载记忆数据
            loadMemory();

            // 加载PDF文件列表
            loadPdfList();

            // 确保聊天容器可见
            function initializeChat() {
                // 如果有保存的对话ID，加载该对话
                if (currentConversationId) {
                    console.log('检测到保存的对话ID:', currentConversationId);
                    const formData = new FormData();
                    formData.append('conversation_id', currentConversationId);

                    fetch('/api/load-conversation', {
                        method: 'POST',
                        body: formData
                    })
                        .then(response => response.json())
                        .then(result => {
                            console.log('加载保存的对话结果:', result);
                            if (result.success) {
                                // 清空聊天区
                                chatContainer.innerHTML = '';

                                // 如果有消息历史，显示消息
                                if (result.messages && result.messages.length > 0) {
                                    // 按时间顺序显示消息
                                    result.messages.forEach(msg => {
                                        if (msg.role === 'user') {
                                            addMessage(msg.content, 'user');
                                        } else if (msg.role === 'assistant') {
                                            addMessage(msg.content, 'ai', false, false); // 不使用打字效果
                                        }
                                    });

                                    // 滚动到底部
                                    setTimeout(() => {
                                        if (chatContainer) {
                                            chatContainer.scrollTop = chatContainer.scrollHeight;
                                        }
                                    }, 200);
                                }
                            } else {
                                console.error('加载保存的对话失败:', result.error);
                                // 清除无效的对话ID
                                localStorage.removeItem('currentConversationId');
                                // 创建新对话
                                createNewConversation();
                            }
                        })
                        .catch(error => {
                            console.error('加载保存的对话失败:', error);
                            // 清除无效的对话ID
                            localStorage.removeItem('currentConversationId');
                            // 创建新对话
                            createNewConversation();
                        });
                } else {
                    // 如果没有保存的对话ID，创建新对话
                    createNewConversation();
                }
            }

            // 确保DOM加载完成后再初始化聊天
            if (document.readyState === 'loading') {
                document.addEventListener('DOMContentLoaded', () => {
                    setTimeout(initializeChat, 300);
                });
            } else {
                setTimeout(initializeChat, 300);
            }

            // 表单提交处理
            queryForm.addEventListener('submit', async function (e) {
                e.preventDefault();

                const question = questionInput.value.trim();
                if (!question) return;

                // 添加用户消息到聊天区，并将本次选择的图片渲染到该消息下方
                const userRow = addMessage(question, 'user');
                try {
                    const previewImgs = document.querySelectorAll('#imagePreview .preview-image');
                    if (previewImgs.length > 0 && userRow) {
                        const msgBubble = userRow.querySelector('.message');
                        if (msgBubble) {
                            const attachments = document.createElement('div');
                            attachments.className = 'chat-attachments';
                            previewImgs.forEach(imgEl => {
                                const src = imgEl.dataset.originalSrc || imgEl.src;
                                const thumb = new Image();
                                thumb.src = src;
                                thumb.className = 'chat-attachment';
                                thumb.title = imgEl.title || '图片';
                                thumb.onclick = function (e) {
                                    e.stopPropagation();
                                    showImagePreview(src, thumb.title);
                                };
                                attachments.appendChild(thumb);
                            });
                            msgBubble.appendChild(attachments);
                        }
                    }
                } catch (e) {
                    console.error('渲染聊天图片附件失败:', e);
                }

                // 清空输入并重置高度
                questionInput.value = '';
                if (questionInput) autoResizeTextarea(questionInput);

                // 显示加载状态
                const loadingMessage = addMessage('正在思考...', 'ai', true);

                try {
                    let response;

                    // 检查是否有图片
                    if (selectedImages.length > 0) {
                        // 多模态查询
                        const formData = new FormData();
                        formData.append('question', question);

                        // 如果有当前对话ID，添加到表单
                        if (currentConversationId) {
                            formData.append('conversation_id', currentConversationId);
                        }

                        // 添加所有图片
                        selectedImages.forEach((file, index) => {
                            console.log(`添加图片 ${index + 1}/${selectedImages.length}: ${file.name}, 大小: ${file.size} 字节`);
                            formData.append('images', file);
                        });

                        try {
                            console.log(`开始发送多模态查询请求，包含 ${selectedImages.length} 张图片`);
                            response = await fetch('/api/multimodal-query', {
                                method: 'POST',
                                body: formData
                            });

                            // 清空图片预览和选择
                            clearImageSelection();
                            console.log('多模态请求已发送，图片已清除');
                        } catch (error) {
                            console.error('多模态查询出错:', error);
                            loadingMessage.remove();
                            addMessage(`图片处理失败: ${error.message}`, 'ai');
                            clearImageSelection();
                            return;
                        }
                    } else {
                        // 文本查询
                        const formData = new FormData();
                        formData.append('question', question);
                        formData.append('search_docs', searchDocsCheck.checked);

                        // 如果有当前对话ID，添加到表单
                        if (currentConversationId) {
                            formData.append('conversation_id', currentConversationId);
                        }

                        response = await fetch('/api/query', {
                            method: 'POST',
                            body: formData
                        });
                    }

                    const result = await response.json();

                    // 移除加载消息
                    loadingMessage.remove();

                    if (result.success) {
                        // 添加AI回复（使用逐字显示效果）
                        await addMessage(result.answer, 'ai');

                        // 更新当前对话ID
                        if (result.conversation_id) {
                            currentConversationId = result.conversation_id;
                            updateConversationStatus();
                        }
                    } else {
                        // 显示错误（使用逐字显示效果）
                        await addMessage(`出错了: ${result.error || '未知错误'}`, 'ai');
                    }

                    // 清空图片预览和选择
                    clearImageSelection();

                } catch (error) {
                    console.error('查询出错:', error);
                    loadingMessage.remove();
                    addMessage('发生错误，请稍后重试', 'ai');
                }
            });

            // 上传PDF文件
            uploadForm.addEventListener('submit', async function (e) {
                e.preventDefault();

                const files = document.getElementById('pdfFile').files;
                if (files.length === 0) {
                    uploadStatus.innerHTML = '<div class="alert alert-warning">请选择PDF文件</div>';
                    return;
                }

                const isGuide = document.getElementById('guideType').checked;
                const includeImages = document.getElementById('includeImagesCheck').checked;

                uploadStatus.innerHTML = '<div class="alert alert-info">正在上传和处理文件...' + (includeImages ? ' (AI正在识别图片)' : '') + '</div>';

                const formData = new FormData();

                if (files.length === 1) {
                    // 单文件上传
                    formData.append('file', files[0]);
                    formData.append('is_guide', isGuide);
                    formData.append('include_images', includeImages);

                    try {
                        const response = await fetch('/api/upload-pdf', {
                            method: 'POST',
                            body: formData
                        });

                        const result = await response.json();

                        if (response.ok) {
                            uploadStatus.innerHTML = `<div class="alert alert-success">成功处理文件: ${files[0].name}</div>`;
                        } else {
                            uploadStatus.innerHTML = `<div class="alert alert-danger">处理失败: ${result.detail || '未知错误'}</div>`;
                        }
                    } catch (error) {
                        console.error('上传出错:', error);
                        uploadStatus.innerHTML = '<div class="alert alert-danger">上传过程中发生错误</div>';
                    }
                } else {
                    // 批量上传
                    for (let i = 0; i < files.length; i++) {
                        formData.append('files', files[i]);
                    }
                    formData.append('is_guide', isGuide);

                    try {
                        const response = await fetch('/api/batch-upload', {
                            method: 'POST',
                            body: formData
                        });

                        const result = await response.json();

                        if (response.ok) {
                            let successCount = 0;
                            let failCount = 0;

                            result.results.forEach(item => {
                                if (item.success) successCount++;
                                else failCount++;
                            });

                            uploadStatus.innerHTML = `<div class="alert alert-info">
                                处理完成: ${successCount}个成功, ${failCount}个失败
                            </div>`;
                        } else {
                            uploadStatus.innerHTML = `<div class="alert alert-danger">批量处理失败</div>`;
                        }
                    } catch (error) {
                        console.error('批量上传出错:', error);
                        uploadStatus.innerHTML = '<div class="alert alert-danger">上传过程中发生错误</div>';
                    }
                }
            });

            // 记忆管理
            memoryForm.addEventListener('submit', async function (e) {
                e.preventDefault();

                const fact = document.getElementById('factInput').value.trim();
                if (!fact) return;

                const isCorrection = document.getElementById('isCorrectionCheck').checked;

                try {
                    const formData = new FormData();
                    formData.append('fact', fact);
                    formData.append('is_correction', isCorrection);

                    const response = await fetch('/api/add-memory', {
                        method: 'POST',
                        body: formData
                    });

                    const result = await response.json();

                    if (result.success) {
                        document.getElementById('factInput').value = '';
                        document.getElementById('isCorrectionCheck').checked = false;

                        // 重新加载记忆
                        loadMemory();
                    }
                } catch (error) {
                    console.error('添加记忆出错:', error);
                    alert('添加记忆失败');
                }
            });

            // 图片上传处理
            imageUpload.addEventListener('change', function (e) {
                const files = e.target.files;
                if (!files || files.length === 0) return;

                const uploadStatus = document.getElementById('uploadStatus');

                // 添加新选择的图片
                for (let i = 0; i < files.length; i++) {
                    const file = files[i];

                    // 检查文件类型
                    if (!file.type.match('image.*')) {
                        uploadStatus.textContent = '只支持图片文件';
                        continue;
                    }

                    // 检查文件大小（限制为5MB）
                    if (file.size > 5 * 1024 * 1024) {
                        uploadStatus.textContent = '图片大小不能超过5MB';
                        continue;
                    }

                    // 添加到选中图片数组
                    const imageIndex = selectedImages.length;
                    selectedImages.push(file);

                    // 创建预览容器
                    const container = document.createElement('div');
                    container.className = 'image-preview-container';
                    container.dataset.index = imageIndex;

                    // 创建预览图片
                    const reader = new FileReader();
                    reader.onload = function (e) {
                        // 创建图片元素
                        const img = document.createElement('img');
                        img.src = e.target.result;
                        img.className = 'preview-image';
                        img.title = file.name;
                        img.dataset.originalSrc = e.target.result; // 保存原始数据URL
                        img.onclick = function (e) {
                            e.stopPropagation(); // 阻止事件冒泡
                            showImagePreview(this.dataset.originalSrc, file.name);
                        };
                        container.appendChild(img);

                        // 创建删除按钮
                        const deleteBtn = document.createElement('div');
                        deleteBtn.className = 'delete-image';
                        deleteBtn.innerHTML = '×';
                        deleteBtn.title = '删除图片';
                        deleteBtn.onclick = function () {
                            // 从数组和预览中移除图片
                            const index = parseInt(container.dataset.index);
                            selectedImages.splice(index, 1);
                            container.remove();

                            // 更新其他图片的索引
                            const containers = imagePreview.querySelectorAll('.image-preview-container');
                            containers.forEach((cont, i) => {
                                cont.dataset.index = i;
                            });

                            // 更新状态
                            uploadStatus.textContent = selectedImages.length > 0 ?
                                `已选择 ${selectedImages.length} 张图片` : '';
                        };
                        container.appendChild(deleteBtn);

                        // 添加到预览区域
                        imagePreview.appendChild(container);

                        // 更新状态
                        uploadStatus.textContent = `已选择 ${selectedImages.length} 张图片`;
                    };
                    reader.readAsDataURL(file);
                }

                // 清空文件输入，以便可以重复选择相同的文件
                imageUpload.value = '';
            });

            // 辅助函数
            // 添加消息到聊天区域
            function svgDataUri(svg) { return 'data:image/svg+xml;charset=UTF-8,' + encodeURIComponent(svg); }
            function getAiAvatar() {
                const svg = '<svg xmlns="http://www.w3.org/2000/svg" width="40" height="40" viewBox="0 0 40 40"><rect width="40" height="40" rx="20" fill="#cbd5e0"/><rect x="12" y="12" width="16" height="12" rx="6" fill="#ffffff"/><circle cx="18" cy="18" r="2" fill="#4a4a4a"/><circle cx="22" cy="18" r="2" fill="#4a4a4a"/><rect x="16" y="22" width="8" height="2" rx="1" fill="#4a4a4a"/><rect x="19" y="8" width="2" height="4" fill="#4a4a4a"/></svg>';
                return svgDataUri(svg);
            }
            function getUserAvatar() {
                const svg = '<svg xmlns="http://www.w3.org/2000/svg" width="40" height="40" viewBox="0 0 40 40"><rect width="40" height="40" rx="20" fill="#6e7376"/><circle cx="20" cy="15" r="6" fill="#ffffff"/><path d="M8 30c0-6 6-10 12-10s12 4 12 10" fill="#ffffff"/></svg>';
                return svgDataUri(svg);
            }
            function addMessage(text, sender, isLoading = false, useTypewriter = true) {
                const row = document.createElement('div');
                row.className = `message-row ${sender === 'ai' ? 'ai' : 'user'}`;
                const avatar = document.createElement('div');
                avatar.className = 'message-avatar';
                const avatarImg = new Image();
                avatarImg.src = sender === 'ai' ? getAiAvatar() : getUserAvatar();
                avatar.appendChild(avatarImg);
                const messageDiv = document.createElement('div');
                messageDiv.className = `message ${sender}-message`;
                row.appendChild(avatar);
                row.appendChild(messageDiv);
                chatContainer.appendChild(row);

                if (isLoading) {
                    // 加载状态显示
                    const loadingSpan = document.createElement('span');
                    loadingSpan.className = 'loading';
                    messageDiv.appendChild(loadingSpan);
                    messageDiv.appendChild(document.createTextNode(' ' + text));
                } else if (sender === 'ai' && useTypewriter) {
                    // AI消息使用打字效果
                    const typingSpan = document.createElement('span');
                    typingSpan.className = 'typing';
                    messageDiv.appendChild(typingSpan);

                    // 确保滚动到底部
                    setTimeout(() => {
                        if (chatContainer) {
                            chatContainer.scrollTop = chatContainer.scrollHeight;
                        }
                    }, 10);

                    // 逐字显示文本，然后把渲染结果当作 Markdown 解析显示（仅 AI 渲染 Markdown）
                    return typewriterEffect(typingSpan, text, 30).then((msgDiv) => {
                        try {
                            // 提取已打完的纯文本
                            const raw = msgDiv.textContent || '';
                            // 使用 marked 解析 Markdown 为 HTML（仅 AI）
                            msgDiv.innerHTML = marked.parse(raw);
                            msgDiv.classList.add('ai-message');

                            // 为代码块添加复制按钮
                            attachCopyButtons(msgDiv);
                        } catch (e) {
                            // 解析失败回退到纯文本
                            msgDiv.textContent = msgDiv.textContent || text;
                        }

                        // 最后确保滚动到底部
                        setTimeout(() => {
                            if (chatContainer) chatContainer.scrollTop = chatContainer.scrollHeight;
                        }, 20);

                        return row;
                    });
                } else {
                    // 非打字效果分支
                    if (sender === 'ai') {
                        // AI 非打字消息 —— 渲染 Markdown
                        try {
                            messageDiv.innerHTML = marked.parse(text);
                            messageDiv.classList.add('ai-message');
                            
                            attachCopyButtons(messageDiv);
                        } catch (e) {
                            messageDiv.textContent = text;
                        }
                    } else {
                        // 用户消息 —— 以纯文本显示，保留换行（不渲染 Markdown）
                        // 使用 textContent 防止 HTML 被解析
                        messageDiv.textContent = text;
            }
                }

                // 确保滚动到底部
                setTimeout(() => {
                    if (chatContainer) {
                        chatContainer.scrollTop = chatContainer.scrollHeight;
                    }
                }, 10);

                return row;
            }

            // 为渲染后的 AI 消息中的代码块添加复制按钮
            function attachCopyButtons(container) {
                if (!container) return;
                try {
                    const preElements = container.querySelectorAll('pre');
                    preElements.forEach(pre => {
                        // 防止重复添加
                        if (pre.dataset.copyBtnAttached) return;
                        pre.dataset.copyBtnAttached = '1';

                        // 如果 <code> 存在，则复制 code 的文本，否则复制 pre 的文本
                        const codeEl = pre.querySelector('code');

                        // 创建复制按钮
                        const btn = document.createElement('button');
                        btn.className = 'code-copy-btn';
                        btn.type = 'button';
                        btn.title = '复制代码';
                        btn.innerText = '复制';

                        // 绑定复制事件
                        btn.addEventListener('click', async function (e) {
                            e.stopPropagation();
                            const textToCopy = codeEl ? codeEl.textContent : pre.textContent;
                            try {
                                await navigator.clipboard.writeText(textToCopy);
                                // 视觉反馈
                                btn.classList.add('copied');
                                btn.innerText = '已复制';
                                setTimeout(() => {
                                    btn.classList.remove('copied');
                                    btn.innerText = '复制';
                                }, 1500);
                            } catch (err) {
                                console.error('复制失败', err);
                                // 退回到选择并提示
                                try {
                                    const range = document.createRange();
                                    range.selectNodeContents(codeEl || pre);
                                    const sel = window.getSelection();
                                    sel.removeAllRanges();
                                    sel.addRange(range);
                                    document.execCommand('copy');
                                    sel.removeAllRanges();
                                } catch (e) {
                                    console.error('回退复制失败', e);
                                }
                            }
                        });

                        // 将按钮放到 pre 内（pre 已设置 position: relative）
                        pre.appendChild(btn);
                    });
                } catch (e) {
                    console.error('attachCopyButtons 出错:', e);
                }
            }

            // 打字机效果
            function typewriterEffect(element, text, speed = 70) {
                return new Promise((resolve) => {
                    // 将文本按换行符分割成行
                    const lines = text.split('\n');
                    let currentLine = 0;
                    let charIndex = 0;

                    const timer = setInterval(() => {
                        if (currentLine < lines.length) {
                            // 当前处理的行
                            const line = lines[currentLine];

                            if (charIndex < line.length) {
                                // 添加当前行的下一个字符
                                element.textContent += line.charAt(charIndex);
                                charIndex++;
                            } else {
                                // 当前行处理完毕，添加换行符并移到下一行
                                if (currentLine < lines.length - 1) {
                                    element.textContent += '\n';
                                }
                                currentLine++;
                                charIndex = 0;
                            }

                            // 确保滚动到底部
                            if (chatContainer) {
                                chatContainer.scrollTop = chatContainer.scrollHeight;
                            }
                        } else {
                            // 所有行都处理完毕
                            clearInterval(timer);
                            // 移除typing类以停止光标闪烁
                            element.classList.remove('typing');

                            // 最后再次确保滚动到底部
                            setTimeout(() => {
                                if (chatContainer) {
                                    chatContainer.scrollTop = chatContainer.scrollHeight;
                                }
                            }, 50);

                            resolve(element.parentElement);
                        }
                    }, speed);

                    // 返回消息div，以便可以在需要时移除
                    return element.parentElement;
                });
            }

            async function loadMemory() {
                try {
                    const response = await fetch('/api/memory');
                    const memory = await response.json();

                    if (memory.facts.length === 0 && memory.corrections.length === 0) {
                        memoryContainer.innerHTML = '<div class="text-muted">暂无记忆数据</div>';
                        return;
                    }

                    let html = '';

                    // 添加事实
                    memory.facts.forEach(fact => {
                        html += `<div class="memory-item">${fact}</div>`;
                    });

                    // 添加纠正
                    memory.corrections.forEach(correction => {
                        html += `<div class="memory-item correction-item">${correction}</div>`;
                    });

                    memoryContainer.innerHTML = html;
                } catch (error) {
                    console.error('加载记忆出错:', error);
                    memoryContainer.innerHTML = '<div class="text-danger">加载记忆失败</div>';
                }
            }

            // 删除记忆处理
            const deleteMemoryForm = document.getElementById('deleteMemoryForm');
            deleteMemoryForm.addEventListener('submit', async function (e) {
                e.preventDefault();

                const index = document.getElementById('memoryIndex').value;
                const isCorrection = document.getElementById('deleteIsCorrectionCheck').checked;

                try {
                    const formData = new FormData();
                    formData.append('index', index);
                    formData.append('is_correction', isCorrection);

                    const response = await fetch('/api/delete-memory', {
                        method: 'POST',
                        body: formData
                    });

                    const result = await response.json();

                    if (result.success) {
                        // 重新加载记忆
                        loadMemory();
                        alert('记忆删除成功');
                    } else {
                        alert(`删除失败: ${result.message}`);
                    }
                } catch (error) {
                    console.error('删除记忆出错:', error);
                    alert('删除记忆失败');
                }
            });

            // 直接检索处理
            const searchForm = document.getElementById('searchForm');
            const searchResults = document.getElementById('searchResults');

            searchForm.addEventListener('submit', async function (e) {
                e.preventDefault();

                const query = document.getElementById('searchQuery').value.trim();
                if (!query) return;

                const collection = document.querySelector('input[name="searchScope"]:checked').value;
                const limit = document.getElementById('resultLimit').value;
                const searchType = document.querySelector('input[name="searchType"]:checked').value;

                searchResults.innerHTML = '<div class="alert alert-info">正在搜索...</div>';

                try {
                    const formData = new FormData();
                    formData.append('query', query);
                    formData.append('collection_name', collection);
                    formData.append('limit', limit);
                    formData.append('search_type', searchType);

                    const response = await fetch('/api/direct-search', {
                        method: 'POST',
                        body: formData
                    });

                    const result = await response.json();

                    if (result.results && result.results.length > 0) {
                        const searchTypeText = result.search_type === 'exact' ? '精确匹配' : '语义搜索';
                        let html = '<div class="alert alert-success">找到 ' + result.results.length + ' 条结果 (' + searchTypeText + ')</div>';
                        html += '<div class="list-group">';

                        result.results.forEach(item => {
                            html += '<div class="list-group-item">';
                            html += '<h6>' + (item.type === 'guide' ? '实验指导书' : '实验报告') + ': ' + item.metadata.filename + ' (第' + item.metadata.page + '页)</h6>';

                            // 如果是精确匹配，显示上下文；如果是语义搜索，显示相似度
                            if (result.search_type === 'exact' && item.context) {
                                html += '<div class="border-start border-4 border-warning ps-3 py-2 mb-2" style="background-color: #fff8e1;">';
                                html += '<div class="small text-muted mb-1">匹配上下文:</div>';
                                html += '<pre style="white-space: pre-wrap; font-size: 0.9rem;">' + item.context + '</pre>';
                                html += '</div>';
                            } else if (item.similarity !== undefined) {
                                html += '<div class="small text-muted mb-2">相似度: ' + (item.similarity * 100).toFixed(2) + '%</div>';
                            }

                            // 显示完整文本（可折叠）
                            const shortText = item.text.substring(0, 300);
                            html += '<details class="mt-2">';
                            html += '<summary class="btn btn-sm btn-outline-secondary">查看完整内容</summary>';
                            html += '<div class="border-start border-4 border-primary ps-3 py-2 mt-2" style="background-color: #f8f9fa;">';
                            html += '<pre style="white-space: pre-wrap; font-size: 0.9rem;">' + item.text + '</pre>';
                            html += '</div>';
                            html += '</details>';

                            html += '</div>';
                        });

                        html += '</div>';
                        searchResults.innerHTML = html;
                    } else {
                        const searchTypeText = result.search_type === 'exact' ? '精确匹配' : '语义搜索';
                        searchResults.innerHTML = '<div class="alert alert-warning">未找到相关内容 (' + searchTypeText + ')</div>';
                    }
                } catch (error) {
                    console.error('搜索出错:', error);
                    searchResults.innerHTML = '<div class="alert alert-danger">搜索过程中发生错误</div>';
                }
            });

            // 刷新PDF列表
            const refreshPdfList = document.getElementById('refreshPdfList');
            refreshPdfList.addEventListener('click', function () {
                loadPdfList();
            });

            // 加载PDF列表
            async function loadPdfList() {
                const guidesList = document.getElementById('guidesList');
                const reportsList = document.getElementById('reportsList');

                try {
                    const response = await fetch('/api/list-pdfs');
                    const result = await response.json();

                    if (result.success) {
                        // 更新指导书列表
                        if (result.guides && result.guides.length > 0) {
                            let html = '';
                            result.guides.forEach(filename => {
                                html += `
                                    <li class="list-group-item d-flex justify-content-between align-items-center pdf-item" data-filename="${filename}" data-is-guide="true">
                                        <span style="cursor: pointer;" class="flex-grow-1 pdf-name">${filename}</span>
                                        <button class="btn btn-sm btn-outline-danger delete-pdf-btn" data-filename="${filename}" data-is-guide="true" title="删除">
                                            <i class="bi bi-trash"></i>
                                        </button>
                                    </li>
                                `;
                            });
                            guidesList.innerHTML = html;
                        } else {
                            guidesList.innerHTML = '<li class="list-group-item text-muted">暂无文件</li>';
                        }

                        // 更新报告列表
                        if (result.reports && result.reports.length > 0) {
                            let html = '';
                            result.reports.forEach(filename => {
                                html += `
                                    <li class="list-group-item d-flex justify-content-between align-items-center pdf-item" data-filename="${filename}" data-is-guide="false">
                                        <span style="cursor: pointer;" class="flex-grow-1 pdf-name">${filename}</span>
                                        <button class="btn btn-sm btn-outline-danger delete-pdf-btn" data-filename="${filename}" data-is-guide="false" title="删除">
                                            <i class="bi bi-trash"></i>
                                        </button>
                                    </li>
                                `;
                            });
                            reportsList.innerHTML = html;
                        } else {
                            reportsList.innerHTML = '<li class="list-group-item text-muted">暂无文件</li>';
                        }
                    } else {
                        guidesList.innerHTML = '<li class="list-group-item text-danger">加载失败</li>';
                        reportsList.innerHTML = '<li class="list-group-item text-danger">加载失败</li>';
                    }
                } catch (error) {
                    console.error('加载PDF列表出错:', error);
                    guidesList.innerHTML = '<li class="list-group-item text-danger">加载失败</li>';
                    reportsList.innerHTML = '<li class="list-group-item text-danger">加载失败</li>';
                }
            }

            // 添加PDF项点击事件 - 使用事件委托
            document.addEventListener('click', async function (e) {
                // 处理删除按钮点击
                if (e.target.classList.contains('delete-pdf-btn') || e.target.closest('.delete-pdf-btn')) {
                    e.stopPropagation();
                    const deleteBtn = e.target.classList.contains('delete-pdf-btn') ? e.target : e.target.closest('.delete-pdf-btn');
                    const filename = deleteBtn.dataset.filename;
                    const isGuide = deleteBtn.dataset.isGuide === 'true';

                    if (confirm(`确定要删除 "${filename}" 吗？\n\n这将同时删除文件和向量数据库中的所有记录。`)) {
                        await deletePdf(filename, isGuide);
                    }
                    return;
                }

                // 处理PDF名称点击 - 查看内容
                if (e.target.classList.contains('pdf-name')) {
                    const item = e.target.closest('.pdf-item');
                    const filename = item.dataset.filename;
                    const isGuide = item.dataset.isGuide === 'true';

                    await showPdfContent(filename, isGuide);
                }
            });

            // 删除PDF
            async function deletePdf(filename, isGuide) {
                try {
                    const formData = new FormData();
                    formData.append('filename', filename);
                    formData.append('is_guide', isGuide);

                    const response = await fetch('/api/delete-pdf', {
                        method: 'POST',
                        body: formData
                    });

                    const result = await response.json();

                    if (result.success) {
                        alert(`成功删除: ${filename}`);
                        // 重新加载PDF列表
                        loadPdfList();
                    } else {
                        alert(`删除失败: ${result.message || '未知错误'}`);
                    }
                } catch (error) {
                    console.error('删除PDF失败:', error);
                    alert('删除失败');
                }
            }

            // 显示PDF内容
            async function showPdfContent(filename, isGuide) {
                const pdfContent = document.getElementById('pdfContent');
                const pdfContentModalLabel = document.getElementById('pdfContentModalLabel');
                const pdfContentModal = new bootstrap.Modal(document.getElementById('pdfContentModal'));

                pdfContent.innerHTML = '<div class="text-center my-5"><div class="spinner-border text-primary" role="status"></div><p class="mt-2">正在加载PDF内容...</p></div>';
                pdfContentModalLabel.textContent = `${isGuide ? '实验指导书' : '实验报告'}: ${filename}`;
                pdfContentModal.show();

                try {
                    const formData = new FormData();
                    formData.append('filename', filename);
                    formData.append('is_guide', isGuide);

                    const response = await fetch('/api/get-pdf-content', {
                        method: 'POST',
                        body: formData
                    });

                    const result = await response.json();

                    if (result.success && result.pages && result.pages.length > 0) {
                        let html = '';

                        result.pages.forEach(page => {
                            html += `<div class="card mb-4">
                                <div class="card-header bg-light">
                                    <h6 class="mb-0">第 ${page.page_number} 页</h6>
                                </div>
                                <div class="card-body">
                                    <pre style="white-space: pre-wrap; font-size: 0.9rem;">${page.content}</pre>
                                </div>
                            </div>`;
                        });

                        pdfContent.innerHTML = html;
                    } else {
                        pdfContent.innerHTML = '<div class="alert alert-warning">无法加载PDF内容</div>';
                    }
                } catch (error) {
                    console.error('加载PDF内容出错:', error);
                    pdfContent.innerHTML = '<div class="alert alert-danger">加载PDF内容时发生错误</div>';
                }
            }

            // 图片预览功能 - 定义为全局函数以便在内联事件中调用
            window.showImagePreview = function (src, title) {
                const modal = document.getElementById('imageModal');
                const modalImg = document.getElementById('modalImage');

                modal.style.display = "block";
                modalImg.src = src;

                // 添加标题（如果需要）
                if (title) {
                    modalImg.alt = title;
                }
            }

            // 关闭图片预览
            document.querySelector('.image-modal-close').onclick = function () {
                document.getElementById('imageModal').style.display = "none";
            }

            // 点击模态框背景也可以关闭
            document.getElementById('imageModal').onclick = function (event) {
                if (event.target === this) {
                    this.style.display = "none";
                }
            }

            // 更新对话状态显示 - 不再显示对话ID
            function updateConversationStatus() {
                // 这里不再显示对话ID，但仍然保留这个函数以便后续可能的状态更新
                // 移除旧的状态显示
                const oldStatus = document.querySelector('.conversation-status');
                if (oldStatus) {
                    oldStatus.remove();
                }
            }

            // 新建对话
            newConversationBtn.addEventListener('click', async function () {
                try {
                    const response = await fetch('/api/create-conversation', {
                        method: 'POST'
                    });

                    const result = await response.json();

                    if (result.success) {
                        currentConversationId = result.conversation_id;

                        // 清空聊天区
                        chatContainer.innerHTML = '';

                        // 添加欢迎消息
                        addMessage('您好！我是计算机网络实验AI助手，可以回答关于网络实验的问题，也可以分析实验截图。请先上传实验指导书和报告，然后开始提问。', 'ai');

                        // 更新状态显示
                        updateConversationStatus();
                    }
                } catch (error) {
                    console.error('创建新对话失败:', error);
                    alert('创建新对话失败');
                }
            });

            // 加载对话列表
            async function loadConversations() {
                try {
                    const response = await fetch('/api/conversations');
                    const result = await response.json();

                    if (result.success && result.conversations) {
                        conversationsList.innerHTML = '';

                        if (result.conversations.length === 0) {
                            conversationsList.innerHTML = '<div class="text-center p-3">没有历史对话</div>';
                            return;
                        }

                        result.conversations.forEach(conv => {
                            const item = document.createElement('a');
                            item.href = '#';
                            item.className = 'list-group-item list-group-item-action';
                            if (conv.id === currentConversationId) {
                                item.classList.add('active');
                            }

                            // 格式化日期
                            const date = new Date(conv.created_at);
                            const formattedDate = `${date.getFullYear()}-${(date.getMonth() + 1).toString().padStart(2, '0')}-${date.getDate().toString().padStart(2, '0')} ${date.getHours().toString().padStart(2, '0')}:${date.getMinutes().toString().padStart(2, '0')}`;

                            item.innerHTML = `
                                <div class="d-flex w-100 justify-content-between">
                                    <h6 class="mb-1">${conv.title}</h6>
                                    <small>${formattedDate}</small>
                                </div>
                                <small>消息数: ${conv.message_count}</small>
                            `;

                            item.addEventListener('click', async function (e) {
                                e.preventDefault();

                                try {
                                    const formData = new FormData();
                                    formData.append('conversation_id', conv.id);

                                    const response = await fetch('/api/load-conversation', {
                                        method: 'POST',
                                        body: formData
                                    });

                                    const result = await response.json();

                                    if (result.success) {
                                        currentConversationId = conv.id;

                                        // 关闭模态框
                                        const modal = bootstrap.Modal.getInstance(document.getElementById('conversationsModal'));
                                        modal.hide();

                                        // 清空聊天区
                                        chatContainer.innerHTML = '';

                                        // 不再添加"已加载对话"提示消息

                                        // 更新状态显示
                                        updateConversationStatus();
                                    } else {
                                        alert('加载对话失败');
                                    }
                                } catch (error) {
                                    console.error('加载对话失败:', error);
                                    alert('加载对话失败');
                                }
                            });

                            conversationsList.appendChild(item);
                        });
                    } else {
                        conversationsList.innerHTML = '<div class="text-center p-3">加载对话列表失败</div>';
                    }
                } catch (error) {
                    console.error('加载对话列表失败:', error);
                    conversationsList.innerHTML = '<div class="text-center p-3">加载对话列表失败</div>';
                }
            }

            // 侧边栏控制
            const toggleSidebarBtn = document.getElementById('toggleSidebarBtn');
            const closeSidebarBtn = document.getElementById('closeSidebarBtn');
            const sidebar = document.getElementById('sidebar');
            const sidebarOverlay = document.querySelector('.sidebar-overlay');

            // 只在对话页面显示侧边栏切换按钮
            function updateSidebarVisibility() {
                // 侧边栏只在聊天标签页中显示，其他标签页不显示
                toggleSidebarBtn.style.display = 'block';
            }

            // 监听标签页切换事件
            document.querySelectorAll('button[data-bs-toggle="tab"]').forEach(tab => {
                tab.addEventListener('shown.bs.tab', function () {
                    updateSidebarVisibility();
                });
            });

            // 初始化时设置可见性
            updateSidebarVisibility();

            // 切换侧边栏
            toggleSidebarBtn.addEventListener('click', function () {
                sidebar.classList.toggle('show');
                const chatContentWrapper = document.getElementById('chat-content-wrapper');

                // 如果打开了侧边栏，调整聊天区域宽度并加载对话列表
                if (sidebar.classList.contains('show')) {
                    chatContentWrapper.classList.remove('col-md-12');
                    chatContentWrapper.classList.add('col-md-9');
                    loadSidebarConversations();
                } else {
                    chatContentWrapper.classList.remove('col-md-9');
                    chatContentWrapper.classList.add('col-md-12');
                }
            });

            // 关闭侧边栏
            closeSidebarBtn.addEventListener('click', function () {
                sidebar.classList.remove('show');
                const chatContentWrapper = document.getElementById('chat-content-wrapper');
                chatContentWrapper.classList.remove('col-md-9');
                chatContentWrapper.classList.add('col-md-12');
            });

            // 侧边栏加载对话列表
            function loadSidebarConversations() {
                try {
                    console.log('正在加载对话列表...');
                    fetch('/api/conversations')
                        .then(response => {
                            console.log('对话列表响应状态:', response.status);
                            return response.json();
                        })
                        .then(result => {
                            console.log('对话列表数据:', result);
                            const sidebarList = document.getElementById('sidebarConversationsList');

                            if (result.success && result.conversations) {
                                sidebarList.innerHTML = '';

                                if (result.conversations.length === 0) {
                                    sidebarList.innerHTML = '<div class="text-center p-3 text-muted">没有历史对话</div>';
                                    return;
                                }

                                // 按更新时间排序，最新的在前面
                                result.conversations.sort((a, b) => new Date(b.updated_at) - new Date(a.updated_at));

                                result.conversations.forEach(conv => {
                                    const item = document.createElement('a');
                                    item.href = '#';
                                    item.className = 'list-group-item list-group-item-action d-flex justify-content-between align-items-center';
                                    if (conv.id === currentConversationId) {
                                        item.classList.add('active');
                                    }

                                    // 格式化日期
                                    const date = new Date(conv.created_at);
                                    const formattedDate = `${date.getFullYear()}-${(date.getMonth() + 1).toString().padStart(2, '0')}-${date.getDate().toString().padStart(2, '0')} ${date.getHours().toString().padStart(2, '0')}:${date.getMinutes().toString().padStart(2, '0')}`;

                                    // 创建主要内容
                                    const contentDiv = document.createElement('div');
                                    contentDiv.className = 'flex-grow-1';
                                    contentDiv.innerHTML = `
                                        <div class="d-flex w-100 justify-content-between">
                                            <h6 class="mb-1">${conv.title}</h6>
                                        </div>
                                        <div class="d-flex w-100 justify-content-between">
                                            <small class="text-muted">${formattedDate}</small>
                                            <small class="text-muted">消息: ${conv.message_count}</small>
                                        </div>
                                    `;

                                    // 创建删除按钮
                                    const deleteBtn = document.createElement('button');
                                    deleteBtn.className = 'btn btn-sm btn-outline-danger ms-2';
                                    deleteBtn.innerHTML = '<i class="bi bi-trash"></i>';
                                    deleteBtn.onclick = function (e) {
                                        e.preventDefault();
                                        e.stopPropagation();

                                        if (confirm('确定要删除这个对话吗？')) {
                                            deleteConversation(conv.id);
                                        }
                                    };

                                    // 组装元素
                                    item.appendChild(contentDiv);
                                    item.appendChild(deleteBtn);

                                    // 点击加载对话
                                    item.addEventListener('click', function (e) {
                                        if (e.target !== deleteBtn && !deleteBtn.contains(e.target)) {
                                            loadConversation(conv.id, conv.title);
                                        }
                                    });

                                    sidebarList.appendChild(item);
                                });
                            } else {
                                sidebarList.innerHTML = '<div class="text-center p-3 text-danger">加载对话列表失败</div>';
                            }
                        })
                        .catch(error => {
                            console.error('加载对话列表失败:', error);
                            document.getElementById('sidebarConversationsList').innerHTML =
                                '<div class="text-center p-3 text-danger">加载对话列表失败</div>';
                        });
                } catch (error) {
                    console.error('加载对话列表出错:', error);
                }
            }

            // 加载对话
            function loadConversation(conversationId, title) {
                try {
                    console.log('加载对话:', conversationId, title);
                    const formData = new FormData();
                    formData.append('conversation_id', conversationId);

                    fetch('/api/load-conversation', {
                        method: 'POST',
                        body: formData
                    })
                        .then(response => response.json())
                        .then(result => {
                            console.log('加载对话结果:', result);
                            if (result.success) {
                                currentConversationId = conversationId;

                                // 保存到本地存储
                                localStorage.setItem('currentConversationId', currentConversationId);

                                // 清空聊天区
                                chatContainer.innerHTML = '';

                                // 不再添加"已加载对话"提示消息

                                // 如果有消息历史，显示消息
                                if (result.messages && result.messages.length > 0) {
                                    // 按时间顺序显示消息
                                    result.messages.forEach(msg => {
                                        if (msg.role === 'user') {
                                            addMessage(msg.content, 'user');
                                        } else if (msg.role === 'assistant') {
                                            addMessage(msg.content, 'ai', false, false); // 不使用打字效果
                                        }
                                    });
                                }

                                // 更新侧边栏
                                loadSidebarConversations();

                                // 滚动到底部
                                chatContainer.scrollTop = chatContainer.scrollHeight;
                            } else {
                                console.error('加载对话失败:', result.error);
                                alert('加载对话失败: ' + (result.error || '未知错误'));
                            }
                        })
                        .catch(error => {
                            console.error('加载对话失败:', error);
                            alert('加载对话失败');
                        });
                } catch (error) {
                    console.error('加载对话失败:', error);
                    alert('加载对话失败');
                }
            }

            // 删除对话
            function deleteConversation(conversationId) {
                try {
                    const formData = new FormData();
                    formData.append('conversation_id', conversationId);

                    fetch('/api/delete-conversation', {
                        method: 'POST',
                        body: formData
                    })
                        .then(response => response.json())
                        .then(result => {
                            if (result.success) {
                                // 如果删除的是当前对话，创建新对话
                                if (currentConversationId === conversationId) {
                                    // 清除本地存储中的对话ID
                                    localStorage.removeItem('currentConversationId');
                                    createNewConversation();
                                }

                                // 重新加载侧边栏
                                loadSidebarConversations();
                            } else {
                                alert('删除对话失败: ' + (result.error || '未知错误'));
                            }
                        })
                        .catch(error => {
                            console.error('删除对话失败:', error);
                            alert('删除对话失败');
                        });
                } catch (error) {
                    console.error('删除对话失败:', error);
                    alert('删除对话失败');
                }
            }

            // 创建新对话
            function createNewConversation() {
                console.log('创建新对话...');
                fetch('/api/create-conversation', {
                    method: 'POST'
                })
                    .then(response => {
                        console.log('创建对话响应状态:', response.status);
                        return response.json();
                    })
                    .then(result => {
                        console.log('创建对话结果:', result);
                        if (result.success) {
                            currentConversationId = result.conversation_id;

                            // 保存到本地存储
                            localStorage.setItem('currentConversationId', currentConversationId);

                            // 清空聊天区
                            chatContainer.innerHTML = '';

                            // 添加欢迎消息
                            addMessage('您好！我是计算机网络实验AI助手，可以回答关于网络实验的问题，也可以分析实验截图。请先上传实验指导书和报告，然后开始提问。', 'ai');

                            // 重新加载侧边栏
                            loadSidebarConversations();
                        } else {
                            alert('创建新对话失败');
                        }
                    })
                    .catch(error => {
                        console.error('创建新对话失败:', error);
                        alert('创建新对话失败');
                    });
            }

            // 侧边栏新建对话按钮
            document.getElementById('newConversationSidebarBtn').addEventListener('click', function () {
                createNewConversation();
            });

            // 原有新建对话按钮
            newConversationBtn.addEventListener('click', function () {
                createNewConversation();
            });

            // 不再初始加载侧边栏，只在点击图标时加载

            // 查看历史图片
            showHistoryImages.addEventListener('click', function () {
                loadHistoryImages();
                const historyImagesModal = new bootstrap.Modal(document.getElementById('historyImagesModal'));
                historyImagesModal.show();
            });

            // 加载历史图片
            async function loadHistoryImages() {
                try {
                    historyImagesContainer.innerHTML = `
                        <div class="text-center w-100 my-5">
                            <div class="spinner-border text-primary" role="status"></div>
                            <p class="mt-2">正在加载图片...</p>
                        </div>
                    `;

                    const response = await fetch('/api/list-images');
                    const result = await response.json();

                    if (result.success && result.images && result.images.length > 0) {
                        let html = '';

                        result.images.forEach(image => {
                            const fileSizeText = formatFileSize(image.size);
                            const dateText = new Date(image.modified * 1000).toLocaleString();

                            html += `
                                <div class="card" style="width: 150px;">
                                    <img src="/uploads/${encodeURIComponent(image.filename)}" class="card-img-top" alt="${image.filename}" 
                                         style="height: 120px; object-fit: cover; cursor: pointer;"
                                         onclick="showImagePreview('/uploads/${encodeURIComponent(image.filename)}', '${image.filename}')">
                                    <div class="card-body p-2">
                                        <p class="card-text small text-truncate" title="${image.filename}">${image.filename}</p>
                                        <p class="card-text small text-muted">${fileSizeText}</p>
                                        <p class="card-text small text-muted">${dateText}</p>
                                    </div>
                                </div>
                            `;
                        });

                        historyImagesContainer.innerHTML = html;
                    } else {
                        historyImagesContainer.innerHTML = '<div class="alert alert-info w-100">暂无上传的图片</div>';
                    }
                } catch (error) {
                    console.error('加载历史图片出错:', error);
                    historyImagesContainer.innerHTML = '<div class="alert alert-danger w-100">加载图片失败</div>';
                }
            }

            // 格式化文件大小
            function formatFileSize(bytes) {
                if (bytes < 1024) return bytes + ' B';
                else if (bytes < 1048576) return (bytes / 1024).toFixed(1) + ' KB';
                else return (bytes / 1048576).toFixed(1) + ' MB';
            }

            function clearImageSelection() {
                selectedImages = [];
                imagePreview.innerHTML = '';
                imageUpload.value = '';
                const uploadStatus = document.getElementById('uploadStatus');
                if (uploadStatus) uploadStatus.textContent = '';
            }
        });
    </script>
</body>

</html>